home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / Gnuplot / Source / readline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-02  |  21.1 KB  |  947 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: readline.c%v 3.38.2.81 1993/02/24 02:29:34 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - readline.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Tom Tkacik
  27.  *
  28.  *   Msdos port and some enhancements:
  29.  *     Gershon Elber and many others.
  30.  * 
  31.  * Send your comments or suggestions to 
  32.  *  info-gnuplot@dartmouth.edu.
  33.  * This is a mailing list; to join it send a note to 
  34.  *  info-gnuplot-request@dartmouth.edu.  
  35.  * Send bug reports to
  36.  *  bug-gnuplot@dartmouth.edu.
  37.  */
  38.  
  39. #ifdef READLINE
  40. #ifdef ATARI
  41. #include "plot.h"
  42. #endif
  43. #ifdef _WINDOWS
  44. #define _Windows
  45. #endif
  46.  
  47. /* a small portable version of GNU's readline */
  48. /* this is not the BASH or GNU EMACS version of READLINE due to Copyleft 
  49.     restrictions */
  50. /* do not need any terminal capabilities except backspace, */
  51. /* and space overwrites a character */
  52.  
  53. /* NANO-EMACS line editing facility */
  54. /* printable characters print as themselves (insert not overwrite) */
  55. /* ^A moves to the beginning of the line */
  56. /* ^B moves back a single character */
  57. /* ^E moves to the end of the line */
  58. /* ^F moves forward a single character */
  59. /* ^K kills from current position to the end of line */
  60. /* ^P moves back through history */
  61. /* ^N moves forward through history */
  62. /* ^H and DEL delete the previous character */
  63. /* ^D deletes the current character, or EOF if line is empty */
  64. /* ^L/^R redraw line in case it gets trashed */
  65. /* ^U kills the entire line */
  66. /* ^W kills last word */
  67. /* LF and CR return the entire line regardless of the cursor postition */
  68. /* EOF with an empty line returns (char *)NULL */
  69.  
  70. /* all other characters are ignored */
  71.  
  72. #include <stdio.h>
  73. #include <ctype.h>
  74. #include <signal.h>
  75.  
  76. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  77.  
  78. /*
  79.  * Set up structures using the proper include file
  80.  */
  81. #ifdef _IBMR2
  82. #define SGTTY
  83. #endif
  84. /*  submitted by Francois.Dagorn@cicb.fr */
  85. #ifdef SGTTY
  86. #include <sgtty.h>
  87. static struct sgttyb orig_termio, rl_termio;
  88. /* define terminal control characters */
  89. static struct tchars s_tchars;
  90. #define VERASE    0
  91. #define VEOF      1
  92. #define VKILL     2
  93. #ifdef TIOCGLTC         /* available only with the 'new' line discipline */
  94. static struct ltchars s_ltchars;
  95. #define VWERASE   3
  96. #define VREPRINT  4
  97. #define VSUSP     5
  98. #endif /* TIOCGLTC */
  99. #define NCCS      6
  100.  
  101. #else /* SGTTY */
  102.  
  103. /* SIGTSTP defines job control */
  104. /* if there is job control then we need termios.h instead of termio.h */
  105. /* (Are there any systems with job control that use termio.h?  I hope not.) */
  106. #ifdef SIGTSTP
  107. #define TERMIOS
  108. #include <termios.h>
  109. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  110. #ifdef ISC22
  111. #ifndef ONOCR            /* taken from sys/termio.h */
  112. #define ONOCR 0000020    /* true at least for ISC 2.2 */
  113. #endif 
  114. #ifndef IUCLC
  115. #define IUCLC 0001000
  116. #endif
  117. #endif /* ISC22 */
  118.  
  119. static struct termios orig_termio, rl_termio;
  120. #else
  121. #include <termio.h>
  122. static struct termio orig_termio, rl_termio;
  123. /* termio defines NCC instead of NCCS */
  124. #define NCCS    NCC
  125. #endif /* SIGTSTP */
  126. #endif /* SGTTY */
  127.  
  128. /* ULTRIX defines VRPRNT instead of VREPRINT */
  129. #ifdef VRPRNT
  130. #define VREPRINT VRPRNT
  131. #endif
  132.  
  133. /* define characters to use with our input character handler */
  134. static char term_chars[NCCS];
  135.  
  136. static int term_set = 0;    /* =1 if rl_termio set */
  137.  
  138. #ifdef NeXT
  139. #define special_getc() ESCgetc()
  140. static char ESCgetc();
  141. #else
  142. #define special_getc() getc(stdin)
  143. #endif
  144.  
  145. #else /* !MSDOS && !ATARI && !_Windows */
  146.  
  147. #ifdef _Windows
  148. #include <windows.h>
  149. #include "win/wtext.h"
  150. #include "win/wgnuplib.h"
  151. extern TW textwin;
  152. #define TEXTUSER 0xf1
  153. #define TEXTGNUPLOT 0xf0
  154. #define special_getc() msdos_getch()
  155. static char msdos_getch();
  156. #endif
  157.  
  158. #if defined(MSDOS) || defined(DOS386)
  159. /* MSDOS specific stuff */
  160. #ifdef DJGPP
  161. #include <pc.h>
  162. #endif
  163. #ifdef __EMX__
  164. #include <conio.h>
  165. #endif
  166. #define special_getc() msdos_getch()
  167. static char msdos_getch();
  168. #endif /* MSDOS */
  169.  
  170. #ifdef ATARI
  171. #include <stdlib.h>
  172. #ifdef __PUREC__
  173. #include <tos.h>
  174. #else
  175. #include <osbind.h>
  176. #endif
  177. #define special_getc() tos_getch()
  178. static char tos_getch();
  179. #endif
  180.  
  181. #endif /* !MSDOS && !ATARI && !_Windows */
  182.  
  183. #if !defined(ATARI)
  184. /* is it <string.h> or <strings.h>?   just declare what we need */
  185. extern int strlen();
  186. extern char *strcpy();
  187. #endif
  188. extern char *alloc();    /* we'll use the safe malloc from misc.c */
  189.  
  190. #define MAXBUF    1024
  191. #define BACKSPACE 0x08    /* ^H */
  192. #define SPACE    ' '
  193.  
  194. struct hist {
  195.     char *line;
  196.     struct hist *prev;
  197.     struct hist *next;
  198. };
  199.  
  200. static struct hist *history = NULL;  /* no history yet */
  201. static struct hist *cur_entry = NULL;
  202.  
  203. static char cur_line[MAXBUF];  /* current contents of the line */
  204. static int cur_pos = 0;    /* current position of the cursor */
  205. static int max_pos = 0;    /* maximum character position */
  206.  
  207.  
  208. void add_history();
  209. static void fix_line();
  210. static void redraw_line();
  211. static void clear_line();
  212. static void clear_eoline();
  213. static void copy_line();
  214. static void set_termio();
  215. static void reset_termio();
  216.  
  217. /* user_putc and user_puts should be used in the place of
  218.  * fputc(ch,stderr) and fputs(str,stderr) for all output
  219.  * of user typed characters.  This allows MS-Windows to 
  220.  * display user input in a different color. */
  221. int
  222. user_putc(ch)
  223. int ch;
  224. {
  225.     int rv;
  226. #ifdef _Windows
  227.     TextAttr(&textwin,TEXTUSER);
  228. #endif
  229.     rv = fputc(ch, stderr);
  230. #ifdef _Windows
  231.     TextAttr(&textwin,TEXTGNUPLOT);
  232. #endif
  233.     return rv;
  234. }
  235.  
  236. int
  237. user_puts(str)
  238. char *str;
  239. {
  240.     int rv;
  241. #ifdef _Windows
  242.     TextAttr(&textwin,TEXTUSER);
  243. #endif
  244.     rv = fputs(str, stderr);
  245. #ifdef _Windows
  246.     TextAttr(&textwin,TEXTGNUPLOT);
  247. #endif
  248.     return rv;
  249. }
  250.  
  251. /* This function provides a centralized non-destructive backspace capability */
  252. /* M. Castro */
  253.  
  254. backspace()
  255. {
  256.     user_putc(BACKSPACE);
  257. }
  258.     
  259. char *
  260. readline(prompt)
  261. char *prompt;
  262. {
  263.  
  264.     unsigned char cur_char;
  265.     char *new_line;
  266.     /* unsigned char *new_line; */
  267.  
  268.     /* set the termio so we can do our own input processing */
  269.     set_termio();
  270.  
  271.     /* print the prompt */
  272.     fputs(prompt, stderr);
  273.     cur_line[0] = '\0';
  274.     cur_pos = 0;
  275.     max_pos = 0;
  276.     cur_entry = NULL;
  277.  
  278.     /* get characters */
  279.     for(;;) {
  280.         cur_char = special_getc();
  281. #ifdef OS2
  282.  /* for emx: remap scan codes for cursor keys */
  283.                 if( cur_char == 0 ) {
  284.                     cur_char = getc(stdin);
  285.                     switch( cur_char){
  286.                         case 75:  /* left, map to ^B */
  287.                             cur_char=2;
  288.                             break ;
  289.                         case 77:  /* right, map to ^F */
  290.                             cur_char=6;
  291.                             break ;
  292.                         case 115: /* ctrl left */
  293.                         case 71:  /* home, map to ^A */
  294.                             cur_char=1;
  295.                             break ;
  296.                         case 116: /* ctrl right */
  297.                         case 79:  /* end, map to ^E */
  298.                             cur_char=5;
  299.                             break ;
  300.                         case 72:  /* up, map to ^P */
  301.                             cur_char=16;
  302.                             break ;
  303.                         case 80:  /* down, map to ^N */
  304.                             cur_char=14;
  305.                             break ;
  306.                         case 83:  /* delete, map to ^D */
  307.                             cur_char=4;
  308.                             break ;
  309.                         default:  /* ignore */
  310.                             cur_char=0;
  311.                             continue ;
  312.                             }
  313.                         }
  314. #endif  /*OS2*/
  315.         if((isprint(cur_char) 
  316. #if defined(ATARI) || defined(_Windows) || defined(MSDOS) || defined(DOS386)
  317.    /* this should be used for all 8bit ASCII machines, I guess */
  318.                     || ((unsigned char)cur_char > 0x7f)
  319. #endif
  320.                                )&& max_pos<MAXBUF-1) {
  321.             int i;
  322.             for(i=max_pos; i>cur_pos; i--) {
  323.                 cur_line[i] = cur_line[i-1];
  324.             }
  325.             user_putc(cur_char);
  326.             cur_line[cur_pos] = cur_char;
  327.             cur_pos += 1;
  328.             max_pos += 1;
  329.             if (cur_pos < max_pos)
  330.                 fix_line();
  331.             cur_line[max_pos] = '\0';
  332.  
  333.         /* else interpret unix terminal driver characters */
  334. #ifdef VERASE
  335.         } else if(cur_char == term_chars[VERASE] ){  /* DEL? */
  336.             if(cur_pos > 0) {
  337.                 int i;
  338.                 cur_pos -= 1;
  339.                 backspace();
  340.                 for(i=cur_pos; i<max_pos; i++)
  341.                     cur_line[i] = cur_line[i+1];
  342.                 max_pos -= 1;
  343.                 fix_line();
  344.             }
  345. #endif /* VERASE */
  346. #ifdef VEOF
  347.         } else if(cur_char == term_chars[VEOF] ){   /* ^D? */
  348.             if(max_pos == 0) {
  349.                 reset_termio();
  350.                 return((char *)NULL);
  351.             }
  352.             if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
  353.                 int i;
  354.                 for(i=cur_pos; i<max_pos; i++)
  355.                     cur_line[i] = cur_line[i+1];
  356.                 max_pos -= 1;
  357.                 fix_line();
  358.             }
  359. #endif /* VEOF */
  360. #ifdef VKILL
  361.         } else if(cur_char == term_chars[VKILL] ){  /* ^U? */
  362.             clear_line(prompt);
  363. #endif /* VKILL */
  364. #ifdef VWERASE
  365.         } else if(cur_char == term_chars[VWERASE] ){  /* ^W? */
  366.             while((cur_pos > 0) &&
  367.                   (cur_line[cur_pos-1] == SPACE)) {
  368.                 cur_pos -= 1;
  369.                 backspace();
  370.             }
  371.             while((cur_pos > 0) &&
  372.                   (cur_line[cur_pos-1] != SPACE)) {
  373.                 cur_pos -= 1;
  374.                 backspace();
  375.             }
  376.             clear_eoline();
  377.             max_pos = cur_pos;
  378. #endif /* VWERASE */
  379. #ifdef VREPRINT
  380.         } else if(cur_char == term_chars[VREPRINT] ){  /* ^R? */
  381.             putc('\n',stderr); /* go to a fresh line */
  382.             redraw_line(prompt);
  383. #endif /* VREPRINT */
  384. #ifdef VSUSP
  385.         } else if(cur_char == term_chars[VSUSP]) {
  386.             reset_termio();
  387.             kill(0, SIGTSTP);
  388.  
  389.             /* process stops here */
  390.  
  391.             set_termio();
  392.             /* print the prompt */
  393.             redraw_line(prompt);
  394. #endif /* VSUSP */
  395.         } else {
  396.             /* do normal editing commands */
  397.             /* some of these are also done above */
  398.             int i;
  399.             switch(cur_char) {
  400.                 case EOF:
  401.                 reset_termio();
  402.                 return((char *)NULL);
  403.                 case 001: /* ^A */
  404.                 while(cur_pos > 0) {
  405.                     cur_pos -= 1;
  406.                     backspace();
  407.                 }
  408.                 break;
  409.                 case 002: /* ^B */
  410.                 if(cur_pos > 0) {
  411.                     cur_pos -= 1;
  412.                     backspace();
  413.                 }
  414.                 break;
  415.                 case 005: /* ^E */
  416.                 while(cur_pos < max_pos) {
  417.                     user_putc(cur_line[cur_pos]);
  418.                     cur_pos += 1;
  419.                 }
  420.                 break;
  421.                 case 006: /* ^F */
  422.                 if(cur_pos < max_pos) {
  423.                     user_putc(cur_line[cur_pos]);
  424.                     cur_pos += 1;
  425.                 }
  426.                 break;
  427.                 case 013: /* ^K */
  428.                 clear_eoline();
  429.                 max_pos = cur_pos;
  430.                 break;
  431.                 case 020: /* ^P */
  432.                 if(history != NULL) {
  433.                     if(cur_entry == NULL) {
  434.                         cur_entry = history;
  435.                         clear_line(prompt);
  436.                         copy_line(cur_entry->line);
  437.                     } else if(cur_entry->prev != NULL) {
  438.                         cur_entry = cur_entry->prev;
  439.                         clear_line(prompt);
  440.                         copy_line(cur_entry->line);
  441.                     }
  442.                 }
  443.                 break;
  444.                 case 016: /* ^N */
  445.                 if(cur_entry != NULL) {
  446.                     cur_entry = cur_entry->next;
  447.                     clear_line(prompt);
  448.                     if(cur_entry != NULL) 
  449.                         copy_line(cur_entry->line);
  450.                     else
  451.                         cur_pos = max_pos = 0;
  452.                 }
  453.                 break;
  454.                 case 014: /* ^L */
  455.                 case 022: /* ^R */
  456.                 putc('\n',stderr); /* go to a fresh line */
  457.                 redraw_line(prompt);
  458.                 break;
  459.                 case 0177: /* DEL */
  460.                 case 010: /* ^H */
  461.                 if(cur_pos > 0) {
  462.                     cur_pos -= 1;
  463.                     backspace();
  464.                     for(i=cur_pos; i<max_pos; i++)
  465.                         cur_line[i] = cur_line[i+1];
  466.                     max_pos -= 1;
  467.                     fix_line();
  468.                 }
  469.                 break;
  470.                 case 004: /* ^D */
  471.                 if(max_pos == 0) {
  472.                     reset_termio();
  473.                     return((char *)NULL);
  474.                 }
  475.                 if(cur_pos < max_pos) {
  476.                     for(i=cur_pos; i<max_pos; i++)
  477.                         cur_line[i] = cur_line[i+1];
  478.                     max_pos -= 1;
  479.                     fix_line();
  480.                 }
  481.                 break;
  482.                 case 025:  /* ^U */
  483.                 clear_line(prompt);
  484.                 break;
  485.                 case 027:  /* ^W */
  486.                 while((cur_pos > 0) &&
  487.                       (cur_line[cur_pos-1] == SPACE)) {
  488.                     cur_pos -= 1;
  489.                     backspace();
  490.                 }
  491.                 while((cur_pos > 0) &&
  492.                       (cur_line[cur_pos-1] != SPACE)) {
  493.                     cur_pos -= 1;
  494.                     backspace();
  495.                 }
  496.                 clear_eoline();
  497.                 max_pos = cur_pos;
  498.                 break;
  499.                 case '\n': /* ^J */
  500.                 case '\r': /* ^M */
  501.                 cur_line[max_pos+1] = '\0';
  502.                 putc('\n', stderr);
  503.                 new_line = (char *)alloc((unsigned long) (strlen(cur_line)+1), "history");
  504.                 strcpy(new_line,cur_line);
  505.                 reset_termio();
  506.                 return(new_line);
  507.                 default:
  508.                 break;
  509.             }
  510.         }
  511.     }
  512. }
  513.  
  514. /* fix up the line from cur_pos to max_pos */
  515. /* do not need any terminal capabilities except backspace, */
  516. /* and space overwrites a character */
  517. static void
  518. fix_line()
  519. {
  520.     int i;
  521.  
  522.     /* write tail of string */
  523.     for(i=cur_pos; i<max_pos; i++)
  524.         user_putc(cur_line[i]);
  525.  
  526.     /* write a space at the end of the line in case we deleted one */
  527.     user_putc(SPACE);
  528.  
  529.     /* backup to original position */
  530.     for(i=max_pos+1; i>cur_pos; i--)
  531.         backspace();
  532.  
  533. }
  534.  
  535. /* redraw the entire line, putting the cursor where it belongs */
  536. static void
  537. redraw_line(prompt)
  538. char *prompt;
  539. {
  540.     int i;
  541.  
  542.     fputs(prompt, stderr);
  543.     user_puts(cur_line);
  544.  
  545.     /* put the cursor where it belongs */
  546.     for(i=max_pos; i>cur_pos; i--)
  547.         backspace();
  548. }
  549.  
  550. /* clear cur_line and the screen line */
  551. static void
  552. clear_line(prompt)
  553. char *prompt;
  554. {
  555.     int i;
  556.     for(i=0; i<max_pos; i++)
  557.         cur_line[i] = '\0';
  558.  
  559.     for(i=cur_pos; i>0; i--)
  560.         backspace();
  561.  
  562.     for(i=0; i<max_pos; i++)
  563.         putc(SPACE, stderr);
  564.  
  565.     putc('\r', stderr);
  566.     fputs(prompt, stderr);
  567.  
  568.     cur_pos = 0;
  569.     max_pos = 0;
  570. }
  571.  
  572. /* clear to end of line and the screen end of line */
  573. static void
  574. clear_eoline(prompt)
  575. char *prompt;
  576. {
  577.     int i;
  578.     for(i=cur_pos; i<max_pos; i++)
  579.         cur_line[i] = '\0';
  580.  
  581.     for(i=cur_pos; i<max_pos; i++)
  582.         putc(SPACE, stderr);
  583.     for(i=cur_pos; i<max_pos; i++)
  584.         backspace();
  585. }
  586.  
  587. /* copy line to cur_line, draw it and set cur_pos and max_pos */
  588. static void
  589. copy_line(line)
  590. char *line;
  591. {
  592.     strcpy(cur_line, line);
  593.     user_puts(cur_line);
  594.     cur_pos = max_pos = strlen(cur_line);
  595. }
  596.  
  597. /* add line to the history */
  598. void
  599. add_history(line)
  600. char *line;
  601. {
  602.     struct hist *entry;
  603.     entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
  604.     entry->line = alloc((unsigned long)(strlen(line)+1),"history");
  605.     strcpy(entry->line, line);
  606.  
  607.     entry->prev = history;
  608.     entry->next = NULL;
  609.     if(history != NULL) {
  610.         history->next = entry;
  611.     }
  612.     history = entry;
  613. }
  614.  
  615. #if defined(MSDOS) || defined(_Windows) || defined(DOS386)
  616.  
  617. /* Convert Arrow keystrokes to Control characters: */
  618. static  char
  619. msdos_getch()
  620. {
  621. #ifdef DJGPP
  622.     char c;
  623.     int ch = getkey();
  624.     c = (ch & 0xff00) ? 0 : ch & 0xff;
  625. #else
  626.     char c = getch();
  627. #endif
  628.  
  629.     if (c == 0) {
  630. #ifdef DJGPP
  631.     c = ch & 0xff;
  632. #else
  633.     c = getch(); /* Get the extended code. */
  634. #endif
  635.     switch (c) {
  636.         case 75: /* Left Arrow. */
  637.         c = 002;
  638.         break;
  639.         case 77: /* Right Arrow. */
  640.         c = 006;
  641.         break;
  642.         case 72: /* Up Arrow. */
  643.         c = 020;
  644.         break;
  645.         case 80: /* Down Arrow. */
  646.         c = 016;
  647.         break;
  648.         case 115: /* Ctl Left Arrow. */
  649.         case 71: /* Home */
  650.         c = 001;
  651.         break;
  652.         case 116: /* Ctl Right Arrow. */
  653.         case 79: /* End */
  654.         c = 005;
  655.         break;
  656.         case 83: /* Delete */
  657.         c = 004;
  658.         break;
  659.         default:
  660.         c = 0;
  661.         break;
  662.     }
  663.     }
  664.     else if (c == 033) { /* ESC */
  665.     c = 025;
  666.     }
  667.  
  668.  
  669.     return c;
  670. }
  671.  
  672. #endif /* MSDOS */
  673.  
  674. #ifdef ATARI
  675.  
  676. /* Convert Arrow keystrokes to Control characters: TOS version */
  677.  
  678. /* the volatile could be necessary to keep gcc from reordering 
  679.    the two Super calls
  680. */
  681. #define CONTERM ((/*volatile*/ char *)0x484L)
  682.  
  683. static void 
  684. remove_conterm()
  685. {
  686.   void *ssp=(void*)Super(0L);
  687.   *CONTERM &= ~0x8;
  688.   Super(ssp);
  689. }
  690.  
  691. static    char
  692. tos_getch()
  693. {
  694.     long rawkey;
  695.     char c;
  696.     int scan_code;
  697.     void *ssp;
  698.     static  int init = 1;
  699.     static  int in_help = 0;
  700.  
  701.     if (in_help) {
  702.     switch(in_help) {
  703.         case 1:
  704.         case 5: in_help++; return 'e';
  705.         case 2:
  706.         case 6: in_help++; return 'l';
  707.         case 3:
  708.         case 7: in_help++; return 'p';
  709.         case 4: in_help = 0; return 0x0d;
  710.         case 8: in_help = 0; return ' ';
  711.     }
  712.     }
  713.  
  714.     if (init) {
  715.     ssp = (void*)Super(0L);
  716.     if( !(*CONTERM & 0x8) ) {
  717.         *CONTERM |= 0x8;
  718.     } else {
  719.         init=0;
  720.     }
  721.     (void)Super(ssp);
  722.     if( init ) {
  723.         atexit(remove_conterm);
  724.         init = 0;
  725.     }
  726.     }
  727.  
  728.    (void)Cursconf(1, 0); /* cursor on */
  729.     rawkey = Cnecin();
  730.     c = (char)rawkey;
  731.     scan_code= ((int)(rawkey>>16)) & 0xff;    /* get the scancode */
  732.     if( rawkey&0x07000000 ) scan_code |= 0x80;     /* shift or control */
  733.  
  734.     switch (scan_code) {
  735.     case 0x62:                /* HELP        */
  736.         if (max_pos==0) {
  737.         in_help = 1;
  738.         return 'h';
  739.         } else {
  740.         return 0;
  741.         }
  742.     case 0xe2:                /* shift HELP    */
  743.         if (max_pos==0) {
  744.         in_help = 5;
  745.         return 'h';
  746.         } else {
  747.         return 0;
  748.         }
  749.     case 0x48: /* Up Arrow */
  750.         return 0x10; /* ^P */
  751.     case 0x50: /* Down Arrow */
  752.         return 0x0e; /* ^N */
  753.     case 0x4b: /* Left Arrow */
  754.         return 0x02; /* ^B */
  755.     case 0x4d: /* Right Arrow */
  756.         return 0x06; /* ^F */
  757.     case 0xcb: /* Shift Left Arrow */
  758.     case 0xf3: /* Ctrl Left Arrow (TOS-bug ?) */
  759.     case 0x47: /* Home */
  760.         return 0x01; /* ^A */
  761.     case 0xcd: /* Shift Right Arrow */
  762.     case 0xf4: /* Ctrl Right Arrow (TOS-bug ?) */
  763.     case 0xc7: /* Shift Home */
  764.     case 0xf7: /* Crtl Home */
  765.         return 0x05; /* ^E */
  766.     case 0x61: /* Undo - redraw line */
  767.         return 0x0c; /* ^L */
  768.     default:
  769.         if (c == 0x1b) return 0x15; /* ESC becomes ^U */
  770.         if (c == 0x7f) return 0x04; /* Del becomes ^D */
  771.         break;
  772.     }
  773.  
  774.     return c;
  775. }
  776.  
  777. #endif /* ATARI */
  778.  
  779. #ifdef NeXT
  780.  
  781. char ESCgetc()
  782. {
  783.   char c;
  784.  
  785.   c=getc(stdin);
  786.   if( c!='\033' ) { /* ESC */
  787.     return c;
  788.   }
  789.   
  790.   c=getc(stdin);
  791.   if( c!='[' ) {
  792.     return c;
  793.   }
  794.   
  795.   c=getc(stdin);
  796.   switch( c ) {
  797.     case 'A': return '\x10'; /* cursor up    becomes ^P */
  798.     case 'B': return '\x0e'; /* cursor down  becomes ^N */
  799.     case 'C': return '\x06'; /* cursor right becomes ^F */
  800.     case 'D': return '\x02'; /* cursor left  becomes ^B */
  801.     default : return c;
  802.   }
  803. }
  804.  
  805. #endif
  806.  
  807.   /* set termio so we can do our own input processing */
  808. static void
  809. set_termio()
  810. {
  811. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  812. /* set termio so we can do our own input processing */
  813. /* and save the old terminal modes so we can reset them later */
  814.     if(term_set == 0) {
  815.         /*
  816.          * Get terminal modes.
  817.          */
  818. #ifdef SGTTY
  819.         ioctl(0, TIOCGETP, &orig_termio);
  820. #else  /* SGTTY */
  821. #ifdef TERMIOS
  822. #ifdef TCGETS
  823.         ioctl(0, TCGETS, &orig_termio);
  824. #else
  825.         tcgetattr(0, &orig_termio);
  826. #endif /* TCGETS */
  827. #else
  828.         ioctl(0, TCGETA, &orig_termio);
  829. #endif /* TERMIOS */
  830. #endif /* SGTTY */
  831.  
  832.         /*
  833.          * Save terminal modes
  834.          */
  835.         rl_termio = orig_termio;
  836.  
  837.         /*
  838.          * Set the modes to the way we want them
  839.          *  and save our input special characters
  840.          */
  841. #ifdef SGTTY
  842.         rl_termio.sg_flags |= CBREAK;
  843.         rl_termio.sg_flags &= ~(ECHO|XTABS);
  844.         ioctl(0, TIOCSETN, &rl_termio);
  845.  
  846.         ioctl(0, TIOCGETC, &s_tchars);
  847.         term_chars[VERASE]   = orig_termio.sg_erase;
  848.         term_chars[VEOF]     = s_tchars.t_eofc;
  849.         term_chars[VKILL]    = orig_termio.sg_kill;
  850. #ifdef TIOCGLTC
  851.         ioctl(0, TIOCGLTC, &s_ltchars);
  852.         term_chars[VWERASE]  = s_ltchars.t_werasc;
  853.         term_chars[VREPRINT] = s_ltchars.t_rprntc;
  854.         term_chars[VSUSP]    = s_ltchars.t_suspc;
  855.  
  856.         /* disable suspending process on ^Z */
  857.         s_ltchars.t_suspc = 0;
  858.         ioctl(0, TIOCSLTC, &s_ltchars);
  859. #endif /* TIOCGLTC */
  860. #else  /* SGTTY */
  861.         rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
  862.         rl_termio.c_iflag |=  (IGNBRK|IGNPAR);
  863.  
  864.         /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
  865.  
  866.         rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  867. #ifdef OS2
  868.  /* for emx: remove default terminal processing */
  869.                 rl_termio.c_lflag &= ~(IDEFAULT);
  870. #endif /* OS2 */
  871.         rl_termio.c_lflag |=  (ISIG);
  872.         rl_termio.c_cc[VMIN] = 1;
  873.         rl_termio.c_cc[VTIME] = 0;
  874.  
  875. #ifndef VWERASE
  876. #define VWERASE 3
  877. #endif
  878.         term_chars[VERASE]   = orig_termio.c_cc[VERASE];
  879.         term_chars[VEOF]     = orig_termio.c_cc[VEOF];
  880.         term_chars[VKILL]    = orig_termio.c_cc[VKILL];
  881. #ifdef TERMIOS
  882.         term_chars[VWERASE]  = orig_termio.c_cc[VWERASE];
  883. #ifdef VREPRINT
  884.         term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
  885. #else
  886. #ifdef VRPRNT
  887.         term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
  888. #endif
  889. #endif
  890.         term_chars[VSUSP]    = orig_termio.c_cc[VSUSP];
  891.  
  892.         /* disable suspending process on ^Z */
  893.         rl_termio.c_cc[VSUSP] = 0;
  894. #endif /* TERMIOS */
  895. #endif /* SGTTY */
  896.  
  897.         /*
  898.          * Set the new terminal modes.
  899.          */
  900. #ifdef SGTTY
  901.         ioctl(0, TIOCSLTC, &s_ltchars);
  902. #else
  903. #ifdef TERMIOS
  904. #ifdef TCSETSW
  905.         ioctl(0, TCSETSW, &rl_termio);
  906. #else
  907.         tcsetattr(0, TCSADRAIN, &rl_termio);
  908. #endif /* TCSETSW */
  909. #else
  910.         ioctl(0, TCSETAW, &rl_termio);
  911. #endif /* TERMIOS */
  912. #endif /* SGTTY */
  913.         term_set = 1;
  914.     }
  915. #endif /* !MSDOS && !ATARI && !defined(_Windows) */
  916. }
  917.   
  918. static void
  919. reset_termio()
  920. {
  921. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  922. /* reset saved terminal modes */
  923.     if(term_set == 1) {
  924. #ifdef SGTTY
  925.         ioctl(0, TIOCSETN, &orig_termio);
  926. #ifdef TIOCGLTC
  927.         /* enable suspending process on ^Z */
  928.         s_ltchars.t_suspc = term_chars[VSUSP];
  929.         ioctl(0, TIOCSLTC, &s_ltchars);
  930. #endif /* TIOCGLTC */
  931. #else  /* SGTTY */
  932. #ifdef TERMIOS
  933. #ifdef TCSETSW
  934.         ioctl(0, TCSETSW, &orig_termio);
  935. #else
  936.         tcsetattr(0, TCSADRAIN, &orig_termio);
  937. #endif /* TCSETSW */
  938. #else
  939.         ioctl(0, TCSETAW, &orig_termio);
  940. #endif /* TERMIOS */
  941. #endif /* SGTTY */
  942.         term_set = 0;
  943.     }
  944. #endif /* !MSDOS && !ATARI && !_Windows */
  945. }
  946. #endif /* READLINE */
  947.